/*
	Simple Software Renderer (SSRenderer)
	Copyright (C) 2007 Piotr Orzechowski <piotr.orzechowski@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "./SDLDevice.h"

namespace deviceSDL
{

using ssr::SSRRenderTarget;
using ssr::SSRSurface;
using ssr::u32;
using ssr::s32;

SSRDevice::SSRDevice()
{
    m_pScreenSurface = NULL;
    m_pWorkingSurface = NULL;
    m_pRenderTarget = NULL;
}

SSRDevice::~SSRDevice()
{
    SDL_FreeSurface(m_pWorkingSurface);

    SSR_RELEASE(m_pRenderTarget);
    ::SDL_Quit();
}

s32 SSRDevice::_CreateDevice(u32 width, u32 height, const char* pTitle)
{
	// Init SDL library
	if (::SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		return -1;
	}

	::freopen("CON", "w", stdout); // redirects stdout
    ::freopen("CON", "w", stderr); // redirects stderr

	// Create window and get pointer to the screen surface
	const SDL_VideoInfo *videoInfo = ::SDL_GetVideoInfo();

	m_pScreenSurface = ::SDL_SetVideoMode(width, height, 32,
							 videoInfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE);
	if (m_pScreenSurface == NULL)
	{
		// Couldn't create primary surface
		return -1;
	}

	// Create the primary rendering target
	m_pRenderTarget = SSRRenderTarget::CreateTarget(width, height);

	// Create a working SDL surface pointing to the render target's color buffer
	SSRSurface* pColorSurface = m_pRenderTarget->GetColorSurface();

	m_pWorkingSurface = ::SDL_CreateRGBSurfaceFrom(pColorSurface->GetBuffer(),
                                                   width, height, 32, m_pScreenSurface->pitch,
											  	   m_pScreenSurface->format->Rmask,
												   m_pScreenSurface->format->Gmask,
												   m_pScreenSurface->format->Bmask,
												   m_pScreenSurface->format->Amask);
	SDL_LockSurface(m_pWorkingSurface);

	// We no longer need the pointer to the color surface
    SSR_RELEASE(pColorSurface);

    if (m_pWorkingSurface == NULL)
    {
        // Couldn't create working surface
        return -1;
    }

	// Set window caption
	::SDL_WM_SetCaption(pTitle, NULL);

	return 0;	// OK
}

void SSRDevice::ToggleFullscreen(bool flag)
{
	if (flag)
	{
		::SDL_WM_ToggleFullScreen(m_pScreenSurface);
	}
}

void SSRDevice::FlushBuffers()
{
	if (m_pRenderTarget != NULL)
	{
		SDL_UnlockSurface(m_pWorkingSurface);

	    ///@todo byc moze uda sie zwiekszyc wydajnosc przez rysowanie bezposrednio do m_pScreenSurface
	    ::SDL_BlitSurface(m_pWorkingSurface, NULL, m_pScreenSurface, NULL);

		SDL_LockSurface(m_pWorkingSurface);

		::SDL_Flip(m_pScreenSurface);
	}
}

SSRRenderTarget* SSRDevice::GetRenderTarget() const
{
    SSR_ADDREF(m_pRenderTarget);
	return m_pRenderTarget;
}

const char* SSRDevice::GetInfo() const
{
	const static char* info = "SSR Display Device - SDL implementation v. 0.01";
	return info;
}

} // namespace
